package com.stoney.handler;

import com.stoney.cache.SpiderCache;
import com.stoney.utils.FilesUtil;
import com.stoney.utils.UrlUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by Stony on 2016/1/8.
 */
public class SpiderHandlerSupport {

    private static final int OPERATION_TIMEOUT = 60 * 1000;
    public static final String regex = "(url[(]{1}[\"']?)([./a-zA-Z0-9-_?=#&:]+)(['\"]?[)]{1})";
    public SpiderAbstractHandler spiderBaseHandler;
    private final static  org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(SpiderHandlerSupport.class);
    public void print(String format,Object...agrs){
        logger.info(String.format(format,agrs));
    }
    public SpiderCache cache;

    private SpiderHandlerSupport(){}
    public SpiderHandlerSupport(SpiderAbstractHandler spiderBaseHandler) {
        this.spiderBaseHandler = spiderBaseHandler;
        this.cache = spiderBaseHandler.getCache();
    }

    public void processUrl(SpiderResource re) {
        if(FilesUtil.isNotEmpty(re.url)){
            if(!containsCache(re.url)){
                if(re.type == SpiderResource.SpiderResourceType.HTML){
                    parsePage(re.url);
                }
                else if(re.type == SpiderResource.SpiderResourceType.CSS){
                    parseCss(re.url);
                }
                else {
                    parseMedia(re.url);
                }
            }
        }
    }
    public void parsePage(String url){
        if(FilesUtil.isEmpty(url)) return;
        Document doc = null;
        print(" * enter parsePage <%s>", url);
        try {
            //header("Cookie", COOKIES)
            doc = Jsoup.connect(url).timeout(OPERATION_TIMEOUT).get();

            Elements links = doc.select("a[href]");
            Elements media = doc.select("[src]");
            Elements imports = doc.select("link[href]");
            print("\nMedia: (%d)", media.size());
            for (Element src : media) {
                if (src.tagName().equals("img")){
                    putResource(src.attr("abs:src"), SpiderResource.SpiderResourceType.MEDIA);
                    print(" * %s: <%s> %sx%s (%s)",src.tagName(), src.attr("abs:src"), src.attr("width"), src.attr("height"),trim(src.attr("alt"), 20));
                }else{
                    putResource(src.attr("abs:src"), SpiderResource.SpiderResourceType.MEDIA);
                    print(" * %s: <%s>", src.tagName(), src.attr("abs:src"));
                }
            }
            print("\nCss Imports: (%d)", imports.size());
            for (Element link : imports) {
                String tagName = link.tagName();
                if(tagName.endsWith(".png") || tagName.endsWith(".gif") || tagName.endsWith(".jpg") || tagName.endsWith(".ico")){
                    putResource(link.attr("abs:href"), SpiderResource.SpiderResourceType.MEDIA);
                    print(" * %s: <%s>", tagName, link.attr("abs:href"));
                }else{
                    putResource(link.attr("abs:href"), SpiderResource.SpiderResourceType.CSS);
                    print(" * %s <%s> (%s)", tagName,link.attr("abs:href"), link.attr("rel"));
                }
            }
            print("\nA Links: (%d)", links.size());
            for (Element link : links) {
                if("a".equals(link.tagName())){
                    print(" * a: <%s>  (%s)", link.attr("abs:href"), trim(link.text(), 35));
                    putResource(link.attr("abs:href"), SpiderResource.SpiderResourceType.HTML);
                }else{
                    print(" * %s: <%s>", link.tagName(), link.attr("abs:href"));
                    putResource(link.attr("abs:href"), SpiderResource.SpiderResourceType.HTML);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            putRepeat(url);
        } finally {
            if(doc != null){
                //------- save page
                savePage(url, doc.html());
            }
        }
    }
    public void parseCss(String url){
        if(FilesUtil.isEmpty(url)) return;
        if(checkNotCss(url)) return;
        print(" * enter parseCss <%s>", url);
        Document doc = null;
        try {
            doc = Jsoup.connect(url).timeout(OPERATION_TIMEOUT).get();
            String baseUri = doc.baseUri();
            Pattern pat = Pattern.compile(regex);
            Matcher mat = pat.matcher(doc.text());
            while(mat.find()){
                String src = mat.group(2);
                if(!isAbsUrl(src)){
                    src = UrlUtil.absUrl(baseUri, src);
                }
                print(" * %s: <%s>", "find", src);
                putResource(src, SpiderResource.SpiderResourceType.MEDIA);
            }
        } catch (Exception e) {
            e.printStackTrace();
            putRepeat(url);
        } finally {
            saveResource(url);
        }
    }
    public void parseMedia(String url){
        if(FilesUtil.isEmpty(url)) return;
        print(" * enter parseMedia <%s>", url);
        if(isCss(url)){
            parseCss(url);
        }else if(isJs(url)){
            parseJs(url);
        }else {
            saveResource(url);
        }
    }
     public void parseJs(String url){
        if(FilesUtil.isEmpty(url)) return;
        try {
            print(" * enter parseJs <%s>", url);
            //no parse js
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            saveResource(url);
        }
    }
     public void saveResource(String url){
        if(containsCache(url)) return;
        if (FilesUtil.saveResource(url, spiderBaseHandler.getSaveDir())) {
            saveCache(url);
        }else{
            putRepeat(url);
        }
    }
     public boolean containsCache(String url){
        return spiderBaseHandler.getCache().contains(url);
    }
    public void savePage(String url,String html){
        if(containsCache(url)) return;
        if(FilesUtil.savePage(url, spiderBaseHandler.getSaveDir(),html)){
            saveCache(url);
        }else{
            putRepeat(url);
        }
    }
    public void putRepeat(String url){

    }
     public void saveCache(String url){
        spiderBaseHandler.getCache().saveValue(url);
    }
     public void putResource(String url,SpiderResource.SpiderResourceType type){
        if(spiderBaseHandler.getSpiderResourceQueue() != null){
            putResource(new SpiderResource(url,type));
        }
    }
    public void putResource(SpiderResource resource){
        if(spiderBaseHandler.getSpiderResourceQueue() == null) return;
        try {
            spiderBaseHandler.getSpiderResourceQueue().offer(resource);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
     public String trim(String s, int width) {
        if (s.length() > width)
            return s.substring(0, width - 1) + ".";
        else
            return s;
    }
     public boolean isAbsUrl(String url){
        return url.startsWith("http:") || url.startsWith("https:");
    }
    public boolean checkStr(String src, String index){
        return src.contains(index) || src.matches(index);
    }
    public boolean isCss(String url){
        if(url.endsWith(".css") || checkStr(url, ".css")){
            return true;
        }
        return false;
    }
    public boolean isJs(String url){
        if(url.endsWith(".js") || checkStr(url, ".js")){
            return true;
        }
        return false;
    }
    public boolean isHtml(String url){
        if(url.endsWith(".html") || checkStr(url, ".html")){
            return true;
        }
        return false;
    }
    public boolean checkNotCss(String url){
        if(url.endsWith(".png") || url.endsWith(".gif") || url.endsWith(".jpg") || url.endsWith(".ico")
                || url.endsWith(".js") || url.endsWith(".html")){
            print(" * %s: <%s>", "img", url);
            return true;
        }
        if(url.endsWith(".ttf") || url.endsWith(".woff") || url.endsWith(".eot") || url.endsWith(".svg")){
            print(" * %s: <%s>", "font", url);
            return true;
        }
        if(checkStr(url,".png") || checkStr(url,".gif") || checkStr(url,".jpg") || checkStr(url,".ico")
                || checkStr(url,".js") || checkStr(url,".html")){
            print(" * %s: <%s>", "img", url);
            return true;
        }
        if(checkStr(url, ".ttf") || checkStr(url, ".woff") || checkStr(url, ".eot") || checkStr(url, ".svg")){
            print(" * %s: <%s>", "font", url);
            return true;
        }
        return false;
    }
}
